home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Utilities / Winter Shell 1.0d2 / Source / Libraries / ApplicationLib / ApplicationLib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-17  |  8.5 KB  |  363 lines  |  [TEXT/KAHL]

  1. /*
  2.     94/01/09 aih
  3.     - added memory resource for setting up memory
  4.     - background notification options are loaded from a resource
  5.     
  6.     94/01/06 aih
  7.     - removed initialization of THINK C's console since I now provide
  8.     my own debug window
  9.     
  10.     94/01/04 aih
  11.     - segments no longer need to be explicitely locked
  12.     
  13.     93/12/31 aih
  14.     - moved VBL task into separate file
  15.     
  16.     93/12/27 aih
  17.     - apple menu is enabled for some modal dialogs so ModalDialog will handle
  18.     editing commands
  19.     
  20.     93/12/15 aih
  21.     - as recommended in Memory, p1-39, changed stack allocation from
  22.     an absolute size to a relative increase, so should work on all machines
  23.     
  24.     93/11/30 aih
  25.     - added VBL task to fill location zero with an odd integer
  26.     
  27.     93/10/29 aih
  28.     - when profiling, the segment containing the profile library is locked
  29.     to prevent an ugly crash due to unbounded recursion via the LoadSeg patch
  30.  
  31.     93/10/23 aih
  32.     - removed some initializations which are no longer needed
  33.     
  34.     93/03/23 AIH
  35.     - Segments are unloaded after initialization
  36.     
  37.     93/03/19 AIH
  38.     - Segments are unloaded and the scrap is loaded when the application
  39.     terminates
  40.     - Toolbox and master pointers are initialized before other initializations
  41.     and before other segments are loaded
  42.     - Moved pre-system 7.0 file open/print from HighLevelEventLib.c
  43.     
  44.     93/03/17 AIH
  45.     - Added menu table parameter
  46.     
  47.     93/03/06 AIH
  48.     - Added thresholds for memory warnings
  49.     
  50.     92/02/29 AIH
  51.     - Added initialization for periodic event library
  52.     
  53.     92/02/27 AIH
  54.     - The draw library no longer needs to be initialized
  55.     
  56.     91/05/26 AIH
  57.     - Using library resources
  58.     
  59.     91/05/14 AIH
  60.     - Added window menu library
  61.     
  62.     91/05/12 AIH
  63.     - Made some small improvements; added Screen Library
  64.     
  65.     91/05/05 AIH
  66.     - Added function to get the creator of the current application
  67.     
  68.     91/04/22 Ari Halberstadt (AIH)
  69.     - Created this library */
  70.  
  71. #if PROFILE && defined(THINK_C)
  72.     #include <profile.h>
  73.     #include <console.h>
  74. #endif
  75.  
  76. #include <stdio.h>
  77. #include <limits.h>
  78. #include "AlertFakeLib.h"
  79. #include "AlertLib.h"
  80. #include "ApplicationLib.h"
  81. #include "ApplicationPreferencesLib.h"
  82. #include "DialogLib.h"
  83. #include "DrawLib.h"
  84. #include "HighLevelEventLib.h"
  85. #include "KeyLib.h"
  86. #include "MacLib.h"
  87. #include "LowMemLib.h"
  88. #include "MemoryLib.h"
  89. #include "MenuLib.h"
  90. #include "NotifyLib.h"
  91. #include "ResourceConstantsLib.h"
  92. #include "ResourceLib.h"
  93. #include "ResourceTypeLib.h"
  94. #include "ScreenLib.h"
  95. #include "SegmentLib.h"
  96. #include "VBLTaskLib.h"
  97.  
  98. /* get the creator of the current application */
  99. OSType AppCreator(void)
  100. {
  101.     FileType fp;
  102.     Handle bndl;
  103.     OSType creator = '????';
  104.     
  105.     FileSetRef(&fp, MacAppRefNum());
  106.     creator = FileCreator(&fp);
  107.     if (creator == 'KAHL' || creator == 'RSED') {
  108.         /* when debugging in THINK C use the 'BNDL' resource */
  109.         bndl = ResGet('BNDL', 128);
  110.         creator = *(OSType *) *bndl;
  111.     }
  112.     return(creator);
  113. }
  114.  
  115. /* initialize profiler */
  116. static void ProfileInit(void)
  117. {
  118.     #if PROFILE && defined(THINK_C)
  119.         console_options.nrows = 10;
  120.         cecho2file("console", 0, stdout);
  121.         InitProfile(1024, 200);
  122.         _profile = true;
  123.         _trace = false;
  124.     #endif
  125. }
  126.  
  127. /* Open or print files using pre-system 7.0 method. Based on listing in
  128.     "Inside Macintosh: Files", p1-35. Returns true if application should
  129.     enter main event loop. */
  130. Boolean AppFilesInit(void)
  131. {
  132.     short nopened = 0;
  133.     volatile short n = 0;
  134.     volatile short i = 1;
  135.     volatile short job = 0;
  136.     AppFile afile;
  137.     FileType file;
  138.     
  139.     TRY {
  140.         CountAppFiles(&job, &n);
  141.         while (i <= n) {
  142.             GetAppFiles(i, &afile);
  143.             FileSetWD(&file, afile.vRefNum, p2cstr(afile.fName));
  144.             if (job == appOpen) {
  145.                 HLEventOpenOne(&file);
  146.                 nopened++;
  147.             }
  148.             else if (job == appPrint)
  149.                 HLEventPrintOne(&file);
  150.             ClrAppFiles(i);
  151.             ++i;
  152.         }
  153.         if (job != appPrint && nopened == 0 && ! MacHasAppleEvents())
  154.             HLEventOpenApplication();
  155.         else if (job == appPrint)
  156.             HLEventPrintOne(NULL);
  157.     } CATCH {
  158.         if (++i <= n) /* skip file */
  159.             RETRY;
  160.         if (job == appPrint)
  161.             HLEventPrintOne(NULL);
  162.     } ENDTRY;
  163.     return(job == appOpen);
  164. }
  165.  
  166. /* create the menu bar */
  167. static void MenuInit(void)
  168. {
  169.     MenuBarGet(RLMBAR);
  170. }
  171.  
  172. /* initialize the application heap */
  173. static void HeapInit(size_t stack, short masters)
  174. {
  175.     SetApplLimit(GetApplLimit() - stack);
  176.     MaxApplZone();
  177.     while (masters-- > 0)
  178.         MoreMasters();
  179. }
  180.  
  181. /* resume procedure installed with InitDialogs */
  182. static pascal void Resume(void)
  183. {
  184.     ExitToShell();
  185. }
  186.  
  187. /* initialize managers */
  188. static void ManagersInit(void)
  189. {
  190.     EventRecord event;
  191.     CursHandle crsr;
  192.     short i;
  193.     
  194.     /* standard initializations */
  195.     InitGraf((Ptr) &thePort);
  196.     InitFonts();
  197.     InitWindows();
  198.     InitMenus();
  199.     TEInit();
  200.     InitDialogs(Resume);
  201.     FlushEvents(everyEvent, 0);
  202.     
  203.     /* so first window will be frontmost */
  204.     for (i = 0; i < 4; i++)
  205.         EventAvail(everyEvent, &event);
  206.  
  207.     /* SetCursor won't move or purge memory */
  208.     crsr = GetCursor(watchCursor);
  209.     if (crsr && *crsr)
  210.         SetCursor(*crsr);
  211. }
  212.  
  213. /* check the system version */
  214. static void VersionCheck(short version)
  215. {
  216.     Str255 str;
  217.     SysEnvRec env;
  218.     
  219.     (void) SysEnvirons(curSysEnvVers, &env);
  220.     if (env.systemVersion < version) {
  221.         GetIndString(str, RLS_ALERT, RLS_ALERT_SYSTEM);
  222.         AlertFakeOk(str, stopIcon);
  223.         FailOSErr(userCanceledErr);
  224.     }
  225. }
  226.  
  227. /* initialize the libraries */
  228. static void LibrariesInit(const ApplicationSettingsType *app)
  229. {
  230.     AlertOptionsType options;
  231.     
  232.     /***
  233.      *** WARNING:    The code up to and including the call to VersionCheck()
  234.      ***                must work with all versions of system software. The
  235.      ***                code up to and including the call to MemInit
  236.      ***                must be in the main segment.
  237.      ***/
  238.  
  239.     VBLInit();
  240.     HeapInit(app->stack, app->masters);
  241.     SegmentsInit();
  242.     ManagersInit();
  243.     AlertFakeInit();
  244.     VersionCheck(app->version);
  245.     MemInit(app->cushion, app->reserve);
  246.     ScreenInit();
  247.     options = **(AlertOptionsHandle) ResGet(RES_NMOP_TYPE, RLNMOP_BACKGROUND);
  248.     AlertOptionsSet(&options);
  249.     MenuInit();
  250.     HLEventInit();
  251.     ProfileInit();
  252.     DlgPreload('ALRT', RLA_OK);
  253.     AppPrefsRead(AppPrefs());
  254. }
  255.  
  256. /* called on exception */
  257. void AppFailed(void)
  258. {
  259.     const char *explanation = gException.explanation;
  260.     CStr255 s;
  261.     char *p = s;
  262.  
  263.     if (FailReason() != userCanceledErr) {
  264.         /* can't use strcpy since may be in different segment */
  265.         while (*explanation) *p++ = *explanation++; *p = 0;
  266.         AlertFakeFailed(FailReason(), c2pstr(s));
  267.     }
  268. }
  269.  
  270. /* initialize the application */
  271. void AppBegin(void)
  272. {
  273.     ApplicationSettingsType app;
  274.     Handle rsrc;
  275.     
  276.     TRY {
  277.         rsrc = GetResource(RES_APP_TYPE, RLAPP_SETTINGS);
  278.         FailNILRes(rsrc);
  279.         app = **(ApplicationSettingsHandle) rsrc;
  280.         LibrariesInit(&app);
  281.         if (MemContiguousSize() < app.minimum) {
  282.             UnloadScrap();
  283.             SegmentsUnload();
  284.             if (MemContiguousSize() < app.minimum)
  285.                 FailOSErr(memFullErr);
  286.         }
  287.     } CATCH {
  288.         AppFailed();
  289.     } ENDTRY;
  290. }
  291.  
  292. /* call after initializing to enter main event loop */
  293. void AppRun(void)
  294. {
  295.     TRY {
  296.         DrawMenuBar();
  297.         if (AppFilesInit()) {
  298.             /* unload segments so that the segment containing the
  299.                 main event loop can be loaded and permanently
  300.                 locked at top of heap */
  301.             SegmentsUnload();
  302.             EventLoopMain();
  303.         }
  304.     } CATCH {
  305.         AppFailed();
  306.     } ENDTRY;
  307. }
  308.  
  309. /* cleanup and exit */
  310. void AppEnd(void)
  311. {
  312.     /* unload segments so there will be room for the scrap */
  313.     #if PROFILE && defined(THINK_C)
  314.         DumpProfile();
  315.     #endif
  316.     SegmentsUnload();
  317.     LoadScrap(); /* see IM-1, p456 */
  318.     ExitToShell(); /* also removes all of our patches */
  319. }
  320.  
  321. void ApplicationAdjustMenu(void)
  322. {
  323.     if (! WinModalHasFocus() || (FocusWindow() && WinHasDrag(FocusWindow())))
  324.         MenuCmdEnable(CMD_APPLE);
  325.     if (WinModalHasFocus() && MacVersion() >= 0x0700 && FrontWindow()) {
  326.         /* In System 7.0, ModalDialog will handle editing commands in the
  327.             Edit menu for modal dialogs. In this application, ModalDialog
  328.             is only used indirectly, via the Standard File Package. Normally,
  329.             all our menus are disabled if a modal window not created by this
  330.             application is front most. To allow ModalDialog to handle editing
  331.             commands we enable the Apple menu and the first item in the Apple
  332.             menu if the front most window is a modal dialog with an edit text
  333.             field and the window was not created directly by this application
  334.             (i.e., WinInitialize was never called for the window). The System
  335.             7.0 behavior of ModalDialog is described in IM-VI, p3-14. */
  336.         WindowPtr front = FrontWindow();
  337.         if (! WinHasExtra(front) &&
  338.                 WinIsDialog(front) &&
  339.                 WinIsModal(front) &&
  340.                ((DialogPeek) front)->editField >= 0)
  341.         {
  342.             MenuEnable(MenuCmdHandle(CMD_APPLE), 0, true);
  343.             MenuEnable(MenuCmdHandle(CMD_APPLE), 1, true);
  344.         }
  345.     }
  346.     if (! WinModalHasFocus())
  347.         MenuCmdEnable(CMD_FILE);
  348.     MenuCmdEnable(CMD_QUIT);
  349. }
  350.  
  351. Boolean ApplicationMenu(const MenuPickType *pick)
  352. {
  353.     Boolean handled = false;
  354.     
  355.     switch (pick->cmd) {
  356.     case CMD_QUIT:
  357.         HLEventQuit();
  358.         handled = true;
  359.         break;
  360.     }
  361.     return(handled);
  362. }
  363.